home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / lbbs07 / msg.c < prev    next >
C/C++ Source or Header  |  1993-07-06  |  23KB  |  1,069 lines

  1. /*
  2.  *    Read/Write a Pandora message base
  3.  *    (LazyBBS Project)
  4.  *   
  5.  *    Public Domain: may be copied and sold freely
  6.  */
  7.  
  8. #include    <stdio.h>
  9. #include    <stdlib.h>
  10. #include    <time.h>
  11. /*#include    <portab.h>*/
  12. #include    <ctype.h>
  13. #include    <string.h>
  14.  
  15. #include    <sys/types.h>    /* for (empty) display in echolist */
  16. #include    <sys/stat.h>
  17.  
  18. #include    "qbbs.h"
  19.  
  20. #include    "bbs.h"
  21. #include    "login.h"
  22. #include    "miscio.h"
  23. #include     "msg.h"
  24. #include    "linedit.h" /* edit_file() */
  25. #include    "sysdep.h"    /* timenix() */
  26.  
  27. #define MAXLINE 23         /* max line / screen */
  28. #define HEADLEN 6         /* displayed message header len */
  29.  
  30. #define MLINLEN 79         /* display message line len */
  31. #define MSGSIZE 32000     /* Max message size */
  32. #define MSGLINE (MSGSIZE/(MLINLEN+1))
  33.  
  34. #define BUFSIZE 1024      /* Copy buffer */
  35. #define USEPID             /* define to use ^PID kludge */
  36. #define PIDSTR    LAZYNAME /* PID name */
  37. #define PIDVER  LAZYVERS /* PID version */
  38.  
  39. /* ===================================================== ECHOLIST */
  40.  
  41. ECHOLIST *el=NULL;
  42. int maxel=0;
  43.  
  44. void close_areas(void )
  45. {
  46.     if(el)
  47.         free(el);
  48. }
  49.  
  50. ECHOLIST *choose_area(char *group)
  51. {
  52.     char temp[BBSSTR];
  53.     int i;
  54.     int j=1;
  55.     int empty=0;
  56.     struct stat mystat;
  57.     ECHOLIST *found=NULL;
  58.     int *numbers=malloc((maxel+1)*sizeof(int));
  59.     
  60.     if(!numbers)
  61.     {
  62.         logline(1,"Can't malloc in choose_area");
  63.         return NULL;
  64.         
  65.     }
  66.     if(!el)
  67.     {
  68.         free(numbers);
  69.         return NULL;
  70.     }
  71.     
  72.     out_printf(CLS_STRING);
  73.     
  74.     out_printf(" #  | Area              | Description\n"
  75.            "----+-------------------+------------------------------------\n");
  76.     for(i=0;i<maxel;i++)
  77.     {
  78.         int bool;
  79.         
  80.         if(group)
  81.             bool=stricmp(group,el[i].group);
  82.         if(!bool || !group)
  83.         {
  84.             empty=0;
  85.             
  86.             strcpy(temp,el[i].file);
  87.             strcat(temp,".HDR");
  88.             
  89.             /* display no number if message base !exist or empty */
  90.             if(!stat(temp,&mystat))
  91.             { /* does exist */
  92.                 if(mystat.st_size==0)
  93.                     empty++;
  94.             }
  95.             else
  96.                 empty++;
  97.             
  98.             if(empty)    
  99.                 out_printf(" %2d | %-17.17s | %s (empty)\n",j,el[i].name,el[i].desc);
  100.             else 
  101.                 out_printf(" %2d | %-17.17s | %s\n",j,el[i].name,el[i].desc);
  102.             numbers[j]=i;
  103.             j++;
  104.         }
  105.     }
  106.     out_printf("\nType the number of your area or <return> to exit: ");
  107.     if(getstring(temp)==BBSOK)
  108.     {
  109.         int tt;
  110.         tt=atoi(temp); 
  111.         if(tt>0 && tt<j)
  112.             found=el+numbers[tt];
  113.     }
  114.     
  115.     free(numbers);
  116.     return found;
  117. }
  118.  
  119. int get_areas(char *path)
  120. {
  121.     FILE *abbs;
  122.     char fname[BBSSTR];
  123.     char curgroup[BBSSTR];
  124.     char curdesc[BBSSTR];
  125.     char buffer[200];
  126.     int i;
  127.     int curarea=0;
  128.     char *ptr;
  129.     
  130.     el=malloc(sizeof(ECHOLIST)*MAXECHO+1);
  131.     if(!el)
  132.     {
  133.         logline(1,"Can't malloc echolist!");
  134.         return BBSFAIL;
  135.     }
  136.     
  137.     strcpy(curgroup,"none");
  138.     strcpy(fname,path);
  139.     strcat(fname,"areas.bbs");
  140.     
  141.     strcpy(curdesc,"No description.");
  142.     
  143.     abbs=fopen(fname,"r");
  144.     if(abbs)
  145.     {
  146.         if(fgets(buffer,199,abbs)!=NULL)
  147.         { /* skip origin line */    
  148.             while(fgets(buffer,199,abbs)!=NULL)
  149.             {
  150.                 strcln(buffer,-1);
  151.                 if(iscomment(*buffer))
  152.                     ;
  153.                 else if(buffer[0]=='-')
  154.                 {
  155.                     if(strnicmp(buffer,"-group",(size_t) strlen("-group"))==0)
  156.                     { /* got new flags */
  157.                         ptr=nextstr(buffer);
  158.                         if(ptr)
  159.                         {
  160.                             if(strlen(ptr)>8)
  161.                                 ptr[8]=0;
  162.                             strlwr(ptr);
  163.                             strspacecpy(curgroup,ptr);
  164.                         }
  165.                     }
  166.                     
  167.                     if(strnicmp(buffer,"-desc",(size_t) strlen("-desc"))==0)
  168.                     { /* got desc */
  169.                         ptr=nextstr(buffer);
  170.                         if(ptr)
  171.                         {
  172.                             if(strlen(ptr)>=BBSSTR-1)
  173.                                 ptr[BBSSTR-2]=0;
  174.                             strcpy(curdesc,ptr);
  175.                         }
  176.                     }                
  177.                 }
  178.                 else /* got an area */
  179.                 {
  180.                     if(strnicmp(buffer,"passthru",strlen("passthru")))
  181.                     { /* !passthru area */
  182.                         strspacecpy(el[curarea].file,buffer);
  183.                         ptr=nextstr(buffer);
  184.                         if(ptr)
  185.                         {
  186.                             strcpy(el[curarea].group,curgroup);
  187.                             strcpy(el[curarea].desc,curdesc);
  188.                             strspacecpy(el[curarea].name,ptr);
  189.  
  190. #ifdef RESERVED_FOR_FUTURE            
  191.                             /* search zone number */
  192.                             el[curarea].zone=defzone;
  193.                             ptr=nextstr(ptr);
  194.                             if(ptr)
  195.                             {
  196.                                 if((ptr[1]==':') || (ptr[2]==':') || (ptr[3]==':') || (ptr[4]==':'))
  197.                                 {
  198.                                     if(isdigit(*ptr))
  199.                                         el[curarea].zone=atoi(ptr);
  200.                                 }
  201.                             }
  202. #endif
  203.  
  204.                             /* next area */
  205.                             if(curarea<(MAXECHO-2))
  206.                                 curarea++;
  207.                         }
  208.                     } /* passthru */
  209.                     /* reset desc */
  210.                     strcpy(curdesc,"No description.");
  211.                 } /* got */
  212.             }
  213.         }
  214.         fclose(abbs);    
  215.         el[curarea].file[0]=0; /* end of list marker */
  216.         
  217.     }
  218.     else
  219.         return BBSFAIL;
  220.         
  221. /* reset desc 
  222.     for(i=0;i<curarea;i++)
  223.         strcpy(el[i].desc, "Unknown.");
  224. */    
  225.     /* reading areafix bbs for descritions */
  226.     strcpy(fname,path);
  227.     strcat(fname,"areafix.bbs");
  228.     
  229.     abbs=fopen(fname,"r");
  230.     if(abbs)
  231.     {
  232.         char cmp[BBSSTR];
  233.         
  234.         while(fgets(buffer,199,abbs)!=NULL)
  235.         {
  236.             if(iscomment(*buffer))
  237.             {
  238.                 strspacecpy(cmp,buffer);
  239.                 ptr=strchr(buffer,';');
  240.                 if(ptr)
  241.                 {
  242.                     if(strlen(ptr)>=BBSSTR-1)
  243.                         ptr[BBSSTR-2]='\0';
  244.                         
  245.                     for(i=0;i<curarea;i++)
  246.                     {
  247.                         if(stricmp(el[i].name, cmp)==0)
  248.                             strcpy(el[i].desc, ptr+1);
  249.                     }
  250.                 }
  251.             }
  252.         }
  253.         fclose(abbs);
  254.     }
  255.         
  256.     maxel=curarea;
  257.     return BBSOK;
  258. }
  259. /* ======================================= post to a pandora message base */
  260.  
  261. int postmsg(char *from, char *fromaddr, char *to, char *toaddr, char *subject, 
  262.                 char *arearad, char *msgtext, int private)
  263. {
  264.     FILE *hdr,*msg,*txt;
  265.     int i,error;
  266.     time_t curtm;
  267.     size_t max;
  268.     long offset,msgsize;
  269.     int dzone=0,dnet=0,dnode=0,dpoint=0;
  270.     int ozone=0,onet=0,onode=0,opoint=0;
  271.     char *zebuffer;
  272.     
  273.     char areahdr[FILENAME_MAX];
  274.     char areamsg[FILENAME_MAX];
  275.     char temp[BBSSTR];
  276.     char zerotemp=0;
  277.     QBBS_MHEADER ourmsg;
  278.     
  279.     zebuffer=malloc(BUFSIZE+1);
  280.     if(!zebuffer)
  281.     {
  282.         logline(1,"can't malloc postmsg buffer");
  283.         return BBSFAIL;
  284.     }
  285.     
  286.     /* convert addresses */
  287.     if(toaddr)
  288.         sscanf(toaddr,"%d:%d/%d.%d",&dzone,&dnet,&dnode,&dpoint);
  289.     sscanf(fromaddr,"%d:%d/%d.%d",&ozone,&onet,&onode,&opoint);
  290.     
  291.     /* create area datafiles names */
  292.     strcpy(areahdr,arearad);
  293.     strcat(areahdr,".HDR");
  294.     strcpy(areamsg,arearad);
  295.     strcat(areamsg,".MSG");
  296.     
  297.     time(&curtm);
  298.     msgsize=0;
  299.     error=0;
  300.     offset=0;
  301.     
  302.     /* old .msg size */
  303.     msg=fopen(areamsg,"rb");
  304.     if(msg)
  305.     {
  306.         fseek(msg,0,SEEK_END);
  307.         offset=ftell(msg);
  308.         if(offset<0)
  309.             offset=0;
  310.         fclose(msg);
  311.     }
  312.             
  313.     /* we gonna write the text in the .msg file */
  314.     msg=fopen(areamsg,"ab");
  315.     if(msg)
  316.     {
  317.         time_t id;
  318.         time(&id);
  319.         
  320.         /* Write MSGID kludge */
  321.         if(opoint==0)
  322.             sprintf(temp,"\01MSGID: %d:%d/%d %8.8lx\x0a",
  323.                 ozone,onet,onode,(long)id);
  324.         else
  325.             sprintf(temp,"\01MSGID: %d:%d/%d.%d %8.8lx\x0a",
  326.                 ozone,onet,onode,opoint,(long)id);
  327.         
  328.         if(fwrite(temp,(size_t) strlen(temp),1,msg)==1)
  329.         {
  330.             msgsize+=strlen(temp);
  331.             
  332.             /* Write PID kludge */
  333.             #ifdef USEPID
  334.             sprintf(temp,"\01PID: %s %s\x0a",PIDSTR,PIDVER);
  335.             if(fwrite(temp,(size_t) strlen(temp),1,msg)==1)
  336.                 msgsize+=strlen(temp);
  337.             else 
  338.                 error++;
  339.             #endif
  340.                 
  341.             /* Read the message itself and add to MSG */
  342.             txt=fopen(msgtext,"r");
  343.             if(txt)
  344.             {
  345.                 error=0;
  346.                 do
  347.                    {
  348.                        max=fread(zebuffer,1,BUFSIZE,txt);
  349.                        if(max>0)
  350.                        {
  351.                         msgsize+=max;
  352.                         if(fwrite(zebuffer,1,max,msg)!=max)
  353.                             error++;
  354.                     }
  355.                     else if(max<0)
  356.                         error++;
  357.                     /* copy only the first MSGSIZE bytes */
  358.                    } while((max==BUFSIZE) && (error==0) && msgsize<MSGSIZE);
  359.                 
  360.                 fclose(txt);
  361.                 
  362.                 /* Write Tearline */
  363. #ifdef USETEAR
  364.                 if(!private)
  365.                 {
  366.                     sprintf(temp,"--- %s %s\x0a",PROGNAME,VERSTR);
  367.                     if(fwrite(temp,(size_t) strlen(temp),1,msg)!=1)
  368.                         error++;
  369.                     msgsize+=strlen(temp);
  370.                 }
  371. #endif
  372.  
  373. #ifndef DONTUSEZERO
  374.                 zerotemp=0;
  375.                 if(fwrite(&zerotemp,(size_t)1,1,msg)!=1)
  376.                         error++;
  377.                 msgsize+=1;
  378. #endif
  379.  
  380.             }
  381.             else
  382.                 error++;                            
  383.         }
  384.         else
  385.             error++;
  386.         
  387.         
  388.         fclose(msg);
  389.     }
  390.     else
  391.         error++;
  392.         
  393.     if(!error)
  394.     {
  395.         /* Init header */
  396.         strcpy(ourmsg.from,from);
  397.         strcpy(ourmsg.to,to);
  398.         strcpy(ourmsg.subject,subject);
  399.         strftime(ourmsg.time,20,"%d %b %y  %H:%M:%S",localtime(&curtm));
  400.         
  401.         ourmsg.stamp=timenix(NULL); 
  402.                     /* fixme? number of seconds since 1/1/70 */
  403.     
  404.         ourmsg.reserved1=0; /* ? */
  405.         ourmsg.reply_to=0; /* set by burep, etc */
  406.         ourmsg.attrib=POSTFLAG;
  407.  
  408.         if(private)
  409.             ourmsg.attrib|=PRVTFLAG;
  410.                     
  411.         for(i=0;i<8;i++)
  412.             ourmsg.mailer[i]=0;
  413.         
  414.         /* Set size and offset */
  415.         ourmsg.size=(UWORD) msgsize;
  416.         ourmsg.msgoffset=offset;
  417.     
  418.         
  419.         ourmsg.read_count=0;
  420.         ourmsg.cost=0;
  421.         ourmsg.o_zone=(WORD) ozone;
  422.         ourmsg.o_net=(WORD) onet;
  423.         ourmsg.o_node=(WORD) onode;
  424.         ourmsg.o_point=(WORD) opoint;
  425.         
  426.         if(dzone)
  427.         {
  428.             ourmsg.d_zone=(WORD) dzone;
  429.             ourmsg.d_net=(WORD) dnet;
  430.             ourmsg.d_node=(WORD) dnode;
  431.             ourmsg.d_point=(WORD) dpoint;
  432.         }
  433.         else
  434.         {
  435.             ourmsg.d_zone=0; 
  436.             ourmsg.d_net=0; 
  437.             ourmsg.d_node=0; 
  438.             ourmsg.d_point=0;
  439.         }
  440.     
  441.         /* And write header */    
  442.         hdr=fopen(areahdr,"ab");
  443.         if(hdr)
  444.         {
  445.             if(fwrite(&ourmsg,sizeof(QBBS_MHEADER),1,hdr)!=1)
  446.                 error++;
  447.             fclose(hdr);
  448.         }
  449.         else 
  450.             error++;
  451.     }
  452.     
  453.     free(zebuffer);
  454.     
  455.     if(error)
  456.     {
  457.         logline(1,"Error while trying to post message");
  458.         return BBSFAIL;
  459.     }
  460.     
  461.     return BBSOK;
  462. }
  463.  
  464. /* ======================================================= message buffer */
  465.  
  466. #define BufLine(a) (buffer+xbufline[a])
  467.  
  468. #define IsNotKludge(a)    ((*a!=1) && strncmp(a,"SEEN-BY:",(size_t)strlen("SEEN-BY:")))
  469.  
  470. /* load_msgbuf: <0 error */
  471.  
  472. int xbufline[MSGLINE]; 
  473.  
  474. /* unsigned bugs, why? */
  475.  
  476. int load_msgbuf(char *file, long index, unsigned int len, char *buffer)
  477. {
  478.     int line=0;
  479.     FILE *ms;
  480.     
  481.     ms=fopen(file,"rb");
  482.     if(ms)
  483.     {
  484.         /* set to index */
  485.         if(fseek(ms,index,SEEK_SET)>=0)
  486.         {
  487.             if(fread(buffer,min(MSGSIZE-1,len),1,ms)!=1)
  488.             {
  489.                 logline(1,"fread error while loading message text");
  490.                 *buffer=0;
  491.                 line=-1;
  492.             } 
  493.             else
  494.             { /* succesfully read */
  495.                 int lastspace=0;
  496.                 int mysize=0;
  497.                 
  498.                 line=1;
  499.                 xbufline[0]=0;
  500.                 
  501.                 while(mysize<min(MSGSIZE-1,len))
  502.                 {
  503.                     /* last space */
  504.                     if(buffer[mysize]==' ')
  505.                         lastspace=mysize;
  506.  
  507.                     /* one more line for \n */
  508.                     if(buffer[mysize]=='\n')
  509.                     {
  510.                         xbufline[line]=lastspace=mysize+1;
  511.                         buffer[mysize]=0;
  512.                         line++;
  513.                     }
  514.                     
  515.                     /* one more line for long lines */
  516.                     if(mysize-xbufline[line-1]>=MLINLEN)
  517.                     {
  518.                         xbufline[line]=max(lastspace,mysize-(MLINLEN/3))+1;
  519.                         buffer[xbufline[line]-1]=0;
  520.                         line++;
  521.                     }
  522.                     
  523.                     /* clean */
  524.                     if(buffer[mysize]<0x20 && buffer[mysize]>1)
  525.                         buffer[mysize]='@';
  526.                 
  527.                     if(line>=MSGLINE-2)
  528.                         break; /* max # of lines */
  529.                                     
  530.                     mysize++;
  531.                 }
  532.             }
  533.         }
  534.         fclose(ms);
  535.     }
  536.     else
  537.         line=-1;
  538.     
  539.     return line-1; /*fixed?*/
  540. }
  541.  
  542. /* new mail */
  543.  
  544. int is_newmail(char *netarea, int *newm, int *newnewm)
  545. {
  546.     char fnam[BBSSTR];
  547.     char user[BBSSTR];
  548.     
  549.     FILE *myfp;
  550.     QBBS_MHEADER curhead;
  551.     
  552.     strcpy(fnam,netarea);
  553.     strcat(fnam,".HDR");
  554.     strcpy(user,get_uname());
  555.     
  556.     *newm=*newnewm=0;
  557.     
  558.     myfp=fopen(fnam,"rb");
  559.     if(!myfp)
  560.     {
  561.         logline(4,"Can't open netmail header %s",fnam);
  562.         return BBSFAIL;
  563.     }
  564.     
  565.     while(fread(&curhead,sizeof(QBBS_MHEADER),1,myfp)==1)
  566.     {
  567.         if(stricmp(curhead.to,user)==0)
  568.         {
  569.             (*newm)++;
  570.             if((curhead.attrib & RCVDFLAG)==0)
  571.                 (*newnewm)++;
  572.         }
  573.     }
  574.     
  575.     fclose(myfp);
  576.     return BBSOK;
  577. }
  578.  
  579. /* ============================================= display list of messages */
  580.  
  581. void list_messages(FILE *hd, char *from, int counter)
  582. {
  583.     QBBS_MHEADER header;
  584.     char anskey;
  585.     int end=0;
  586.     int i;
  587.  
  588.     out_printf(CLS_STRING);
  589.     out_printf("Nb  From                 To                   Subject\n"
  590.            "--------------------------------------------------------------------------\n");
  591.     
  592.     while(1)
  593.     {
  594.         i=2;
  595.         while(i<MAXLINE)
  596.         {
  597.             if(fread(&header,sizeof(QBBS_MHEADER),1,hd)!=1)
  598.             {
  599.                 end++;
  600.                 break;
  601.             }
  602.             counter++; /* increment display counter */
  603.  
  604.             
  605.             if(
  606.                 (
  607.                     (    ((header.attrib & PRVTFLAG)==0)        /* not pvt */
  608.                      ||    (stricmp(from,header.from)==0)         /* from guy */
  609.                      ||  (stricmp(from,header.to)==0)  )        /* to guy */
  610.                     &&
  611.                     ((header.attrib & KILLFLAG)==0) 
  612.                 )
  613.                    || 
  614.                    isgod()
  615.                )
  616.             { 
  617.                 out_printf("%-3.3d %-20.20s %-20.20s %-30.30s\n",counter,header.from,header.to,header.subject);
  618.                 i++;
  619.             }
  620.         }
  621.         
  622.         if(end)
  623.         {
  624.             out_printf("\nEnd of list. Type [return].\n");
  625.             getkey();
  626.             break;
  627.         }
  628.         
  629.         out_printf("\n[M]ore [B]ack to messages ?");
  630.         
  631.         anskey=toupper(getkey());
  632.         if(anskey!='M' && anskey!=' ')
  633.             break;
  634.         
  635.         out_printf("\n");
  636.     } /* main loop */
  637. }
  638.  
  639. /* ======================= read a message base, should log itself errors */
  640.  
  641. void read_messages(char *area, char *path, char *from, 
  642.         char *fromaddr, int pvt, int okwrite)
  643. {
  644.     char *buffer;
  645.     int msgidx,maxline;
  646.     long nbmsg;
  647.     int no=0;
  648.     int did,nodisplay;
  649.     int doquote=0;
  650.     int previous=0;
  651.     int havedisplayed=0;
  652.     int true, curline,i;
  653.     FILE *hd, *quotef;
  654.     QBBS_MHEADER curhead;
  655.     char areahdr[FILENAME_MAX];
  656.     char areamsg[FILENAME_MAX];
  657.     char entb[30];
  658.     int retchar;
  659.     
  660.     buffer=malloc(MSGSIZE);
  661.     if(buffer)
  662.     {
  663.         logline(3,"Reading area %s",area);
  664.         out_printf(CLS_STRING);
  665.         out_printf("Loading...\n");
  666.  
  667.         /* create area datafiles names */
  668.         strcpy(areahdr,path);
  669.         strcat(areahdr,".HDR");
  670.         strcpy(areamsg,path);
  671.         strcat(areamsg,".MSG");
  672.     
  673.         hd=fopen(areahdr,pvt ? "rb+" : "rb"); /* write to update rcvd flag */
  674.         if(hd)
  675.         {
  676.             /* check empty */
  677.             fseek(hd,0,SEEK_END);
  678.             nbmsg=ftell(hd);
  679.             if(nbmsg>0)
  680.             {
  681.                 nbmsg=nbmsg/sizeof(QBBS_MHEADER);
  682.                 rewind(hd);
  683.                                     
  684.                 msgidx=0;
  685.                 
  686.                 /* find "lastread", place on stamp based on last login */
  687.                 if(!pvt) /* echomail: first new message since last login (DAY(stamp)>LAST_LOGIN) */
  688.                 {
  689.                     int idx=0;
  690.                     int last=get_ulastlogin();
  691.                     
  692.                     while(fread(&curhead,sizeof(QBBS_MHEADER),1,hd)==1)
  693.                     {
  694.                         if(curhead.stamp/86400>=last)
  695.                         {
  696.                             msgidx=idx;
  697.                             break;
  698.                         }
  699.                         idx++;
  700.                     }
  701.                 }
  702.                 else /* pvt: 1st message !rcv */
  703.                 {
  704.                     int idx=0;
  705.                     
  706.                     while(fread(&curhead,sizeof(QBBS_MHEADER),1,hd)==1)
  707.                     {
  708.                         if( ((curhead.attrib & RCVDFLAG)==0)
  709.                           && (stricmp(from,curhead.to)==0) )
  710.                         {
  711.                             msgidx=idx;
  712.                             break;
  713.                         }
  714.                         idx++;
  715.                     }
  716.                 }
  717.                 
  718.                 
  719.                 out_printf(CLS_STRING);
  720.                 
  721.                 /* message loop */
  722.                 do {
  723.                     nodisplay=0;
  724.                     
  725.                     /* read header msgidx */
  726.                     if(fseek(hd,sizeof(QBBS_MHEADER)*msgidx,SEEK_SET)<0)
  727.                     {
  728.                         logline(4,"fseek() error on %s",areahdr);
  729.                         break;
  730.                     }
  731.                     if(fread(&curhead,sizeof(QBBS_MHEADER),1,hd)!=1)
  732.                     {
  733.                         logline(4,"fread() error on %s",areahdr);
  734.                         break;
  735.                     }
  736.                     
  737.                     if(pvt) /* netmail */
  738.                     {
  739.                         if(
  740.                             !isgod()
  741.                           &&
  742.                             ( ((curhead.attrib & PRVTFLAG)==0)
  743.                             || ((curhead.attrib & KILLFLAG)!=0)
  744.                             || ( (stricmp(from,curhead.from)!=0)
  745.                             && (stricmp(from,curhead.to)!=0) ) )
  746.                           )
  747.                               nodisplay++;
  748.                         /*{
  749.                             if(msgidx<nbmsg-1)
  750.                                 msgidx++;
  751.                             else
  752.                                 break;
  753.                             nodisplay++; 
  754.                         }*/
  755. /* fixme, afficher un msg ? */
  756.                     }
  757.                     else if((curhead.attrib & KILLFLAG) || 
  758.                         (curhead.attrib & PRVTFLAG))
  759.                         nodisplay++;
  760.                     
  761.                     if(nodisplay)/* search a displayable message */
  762.                     { /* echomail */
  763.                         if(msgidx<nbmsg-1 && !previous)
  764.                             msgidx++;
  765.                         else if(msgidx>0 && previous)
  766.                             msgidx--;
  767.                         else
  768.                             break;
  769.                     }
  770.                     else
  771.                     { /* display message */
  772.                         previous=0; /* we finally got one backwards, can reset flag */
  773.                         havedisplayed++;
  774.                             
  775.                         if(pvt) /* netmail: log & update rcvd flag */
  776.                         {
  777.                             if( ((curhead.attrib & RCVDFLAG)==0)
  778.                               && (stricmp(from,curhead.to)==0) )
  779.                             {
  780.                                 logline(1,"User reading netmail from %s to %s",
  781.                                             curhead.from,curhead.to);
  782.                                 curhead.attrib|=RCVDFLAG;
  783.                             
  784.                                 /* update header */
  785.                                 if(fseek(hd,sizeof(QBBS_MHEADER)*msgidx,SEEK_SET)<0)
  786.                                 {
  787.                                     logline(4,"fseek() error on %s",areahdr);
  788.                                     break;
  789.                                 }
  790.                                 
  791.                                 if(fwrite(&curhead,sizeof(QBBS_MHEADER),1,hd)!=1)
  792.                                     logline(4,"Write error during rcvd flag update");
  793.                             }
  794.                         } /* end update rcvd flag */
  795.                     
  796.                         out_printf(CLS_STRING);
  797.                         /* display header */
  798.                         out_printf("[message %d/%d of %s]\n",
  799.                             msgidx+1,(int)nbmsg,area);
  800.                         
  801.                         if(pvt)
  802.                         {
  803.                             out_printf("From : %s on %d:%d/%d.%d\n",
  804.                                 curhead.from,curhead.o_zone,curhead.o_net,
  805.                                 curhead.o_node,curhead.o_point);
  806.                             out_printf("To   : %s on %d:%d/%d.%d\n",
  807.                                 curhead.to,curhead.d_zone,curhead.d_net,
  808.                                 curhead.d_node,curhead.d_point);
  809.                         }
  810.                         else
  811.                             out_printf("From : %s\nTo   : %s\n",curhead.from,curhead.to);
  812.                         
  813.                         out_printf("Date : %s\nSubj.: %s\n"
  814.                             "==========================================================================\n",
  815.                             curhead.time,curhead.subject);
  816.  
  817.                         /* display message */
  818.                         true=1;
  819.                         curline=0;
  820.                         
  821.                         /* load the message */
  822.                         maxline=load_msgbuf(areamsg,curhead.msgoffset,
  823.                                 (unsigned int)curhead.size,buffer);
  824.                         
  825.                         if(maxline<=0)
  826.                         {
  827.                             out_printf(CLS_STRING);
  828.                             out_printf("No message.\n");
  829.                             break;
  830.                         }
  831.                         
  832.                         curline=i=0;
  833.                         while(i<(MAXLINE-HEADLEN))
  834.                         {
  835.                             if(curline>=maxline) 
  836.                                 break;
  837.                             if(IsNotKludge(BufLine(curline)) || isgod())
  838.                             {
  839.                                 out_string(BufLine(curline));
  840.                                 out_printf("\n");
  841.                                 i++;
  842.                             }
  843.                             curline++;
  844.                         }
  845.                         
  846.                         true=1;
  847.                         while(true) /* scroll loop inside message */
  848.                         {
  849.                             if(okwrite)
  850.                                 out_printf("[M]ore [H]ome / [P]revious [N]ext [G]oto msg / [L]ist [R]eply [Q]uit ?");
  851.                             else
  852.                                 out_printf("[M]ore [H]ome / [P]revious [N]ext [G]oto message / [L]ist [Q]uit ?"); 
  853.                             retchar=getkey();
  854.                             retchar=toupper(retchar);
  855.                             out_printf(ERASE_LINE);
  856.                             switch(retchar)
  857.                             {
  858.                                 /* MORE of the message */
  859.                                 case 'M':
  860.                                 case ' ':
  861.                                 case '\r': /* cr */
  862.                                 did=0;
  863.                                 for(i=0;i<MAXLINE-5;i++)
  864.                                 {
  865.                                     if(curline<maxline)
  866.                                     {
  867.                                         if(IsNotKludge(BufLine(curline)) || isgod())
  868.                                         {
  869.                                             out_string(BufLine(curline));
  870.                                             out_printf("\n");
  871.                                         }
  872.                                         curline++;
  873.                                         did++;
  874.                                     }
  875.                                     else
  876.                                         break;
  877.                                 }
  878.                                 if(!did) /* if end of page, next message */
  879.                                 {
  880.                                     retchar='>';
  881.                                     true=0;
  882.                                 }
  883.                                 break;
  884.                                                     
  885.                                 /* MORE line */
  886.                                 case '+':
  887.                                 /* case DOWNARROW:*/
  888.                                 if(curline<maxline)
  889.                                 {
  890.                                     out_string(BufLine(curline));
  891.                                     out_printf("\n");
  892.                                     curline++;
  893.                                 }
  894.                                 break;
  895.                                 
  896.                                 /* All other keys */
  897.                                 case 'R': /* quote current mail */
  898.                                 if(okwrite)
  899.                                 { /* if allowed to write */
  900.                                     doquote++;
  901.                                     quotef=fopen(tempfile(),"w");
  902.                                     if(quotef)
  903.                                     {
  904.                                         fprintf(quotef,"In a message of <%s>, %s writes:\n\n",
  905.                                             curhead.time,curhead.from);
  906.                                         for(i=0;i<maxline;i++)
  907.                                         {
  908.                                             if(IsNotKludge(BufLine(i)))
  909.                                                 fprintf(quotef,"> %-65.65s\n",BufLine(i));
  910.                                         }
  911.                                         fclose(quotef);
  912.                                     }
  913.                                     else
  914.                                         logline(3,"Can't open tempfile.");
  915.                                 }
  916.                                 /* end of processing after fclose()s */
  917.                                 case 'P':
  918.                                 case '<':
  919.                                 /*case LEFTARROW:*/
  920.                                 case 'N':
  921.                                 case '>':
  922.                                 /*case RIGHTARROW:*/
  923.                                 case 'G':
  924.                                 case 'Q':
  925.                                 case '!':
  926.                                 case 'H':
  927.                                 case 'L':
  928.                                 case '-':
  929.                                 case '*':
  930.                                 case 3: /* ctrl+C */
  931.                                 true=0;
  932.                                 break;
  933.                             }
  934.                         } /* end scroll loop inside message */
  935.                         
  936.                         if(retchar=='Q' || retchar=='\03' 
  937.                             || retchar=='!' || retchar=='R')
  938.                             break; /* bye */
  939.                         else switch(retchar)
  940.                         {
  941.                             /* list messages */
  942.                             case 'L':
  943.                             list_messages(hd,from,msgidx+1); 
  944.                             /* HOME */
  945.                             case '*':
  946.                             case 'H':
  947.                             case '-':
  948.                             out_printf(CLS_STRING);
  949.                             break;
  950.                             
  951.                             /* previous message */
  952.                             case 'P':
  953.                             case '<':
  954.                             /* case LEFTARROW:*/
  955.                             if(msgidx>0)
  956.                             {
  957.                                 msgidx--;
  958.                                 previous++;
  959.                             }
  960.                             else
  961.                                 out_printf("\7");
  962.                             break;
  963.  
  964.                             /* next message */                            
  965.                             case 'N':
  966.                             case '>':
  967.                             /* case RIGHTARROW:*/
  968.                             if(msgidx<nbmsg-1)
  969.                                 msgidx++;
  970.                             else
  971.                                 out_printf("\7");
  972.                             break;
  973.                             
  974.                             /* goto message */
  975.                             case 'G':
  976.                             out_printf(CLS_STRING);
  977.                             out_printf("\nGoto message number (<Return> to cancel)?");
  978.                             if(getstring(entb)==BBSOK)
  979.                             {
  980.                                 msgidx=atoi(entb)-1;
  981.                                 if(msgidx<0 || msgidx>=nbmsg)
  982.                                     msgidx=0;
  983.                             }
  984.                             out_printf("\n");
  985.                             break;
  986.                         }
  987.                     } /* nodisplay */
  988.                 } while(retchar!='Q' && retchar!='\03' && retchar!='!');
  989.                 /* ctrl+C, Q */
  990.             }
  991.             else
  992.                 no++;
  993.                 
  994.             fclose(hd);
  995.         }
  996.         else
  997.             no++;
  998.             
  999.         /* finish quote processing */
  1000.         if(doquote)
  1001.         {
  1002.             char toaddr[BBSSTR];
  1003.     
  1004.             if(is_uguest())
  1005.             {
  1006.                 out_printf(CLS_STRING);
  1007.                 out_printf("Guest user can't quote mail.\n\n[Return]\n");
  1008.                 getkey();
  1009.             }
  1010.             else
  1011.             {
  1012.                 logline(5,"User trying to quote mail (%s)",area);
  1013.                 out_printf("\n\nDo you really want to quote mail? [Y/n]");
  1014.     
  1015.                 if(tolower(getkey())!='n')
  1016.                 {
  1017.                     out_printf(CLS_STRING);
  1018.                     out_printf("    This will be a %s message to %s.\n",
  1019.                             pvt ? "PRIVATE" : "*PUBLIC*", 
  1020.                             pvt ? curhead.from : area);
  1021.                             
  1022.                     out_printf("    Subject: %s.\n",curhead.subject);
  1023.     
  1024.                     sprintf(toaddr,"%d:%d/%d.%d",
  1025.                                 curhead.o_zone,curhead.o_net,
  1026.                                 curhead.o_node,curhead.o_point);
  1027.                                 
  1028.                     if(edit_file(tempfile())==BBSOK)
  1029.                     {
  1030.                         out_printf("\n\nDo you want to send your mail to %s on %s [y/N]?\n",
  1031.                             curhead.from, pvt ? toaddr : area);
  1032.         
  1033.                         if(tolower(getkey())=='y')
  1034.                         {
  1035.                             if(pvt)
  1036.                                 logline(2,"User wrote netmail to %s",curhead.from);
  1037.                             else
  1038.                                 logline(2,"User wrote echomail in area %s",area);
  1039.                                 
  1040.                             postmsg(get_uname(),fromaddr,curhead.from,toaddr,
  1041.                                 curhead.subject,path,tempfile(),pvt);
  1042.                         }
  1043.                     }
  1044.                 }
  1045.             }
  1046.             remove(tempfile());
  1047.         } /* quote */
  1048.         
  1049.         if(no)
  1050.         {
  1051.             logline(3,"No message base %s",areahdr);
  1052.             out_printf(CLS_STRING);
  1053.             out_printf("No message base!\n\n");
  1054.             out_printf("Type a key.\n");
  1055.             getkey();
  1056.         }
  1057.         
  1058.         if(pvt && !havedisplayed)
  1059.         {
  1060.             out_printf("You have no mail waiting! Hit [Return].\n");
  1061.             getkey();
  1062.         }
  1063.         
  1064.         free(buffer);
  1065.     }
  1066.     else
  1067.         logline(4,"Can't allocate message buffer");
  1068. }
  1069.